package simple.utils.data.serializers;

import com.google.protobuf.Message;
import com.google.protobuf.Parser;
import simple.utils.data.Bytes;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

/**
 * Created by martin on 7.5.14.
 */
public class GPBMessageSerializer implements Serializer<Message> {

    private static final int INT_LEN = 4;

    @Override
    public byte[] toBytes(Message message) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] clsNameBytes = message.getClass().getName().getBytes(StandardCharsets.UTF_8);
        int len = clsNameBytes.length;
        bos.write(Bytes.intToBytes(len));
        bos.write(clsNameBytes);
        bos.write(message.toByteArray());
        bos.flush();
        return bos.toByteArray();
    }

    @Override
    public Message fromBytes(byte[] data) throws IOException {
        int clsNameLen = Bytes.bytesToInt(Arrays.copyOf(data, INT_LEN)); // int bytes
        String clsName = new String(Arrays.copyOfRange(data, INT_LEN, INT_LEN + clsNameLen));
        Class cls = null;

        try {
            cls = Class.forName(clsName);
            Method parseFrom = cls.getMethod("parseFrom", byte[].class);
            Object invoke = parseFrom.invoke(null, Arrays.copyOfRange(data, INT_LEN + clsNameLen, data.length));
            return (Message) invoke;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
